<template>
  <div class="image-upload">
    <el-upload
      ref="uploadRef"
      :action="uploadUrl"
      :headers="uploadHeaders"
      :data="uploadData"
      :show-file-list="false"
      :before-upload="beforeUpload"
      :on-success="handleSuccess"
      :on-error="handleError"
      :disabled="disabled"
    >
      
    <div class="image-uploader">

      <div v-if="imageUrl" class="image-preview">
        <div v-if="imageLoading" class="image-loading">
          <el-icon class="loading-icon">
            <Loading />
          </el-icon>
          <div class="loading-text">加载中...</div>
        </div>

        <div v-else-if="imageError" class="image-error">
          <el-icon class="error-icon">
            <Picture />
          </el-icon>
          <div class="error-text">图片加载失败</div>
        </div>

        <img
          v-else
          :src="imageUrl"
          :alt="alt"
          class="uploaded-image"
          :style="{
            objectFit: props.fit,
            objectPosition: 'center center'
          }"
          
          @load="handleImageLoad"
          @error="handleImageError"
          @loadstart="handleImageLoadStart"
        />
        <div class="image-overlay">
          <div class="overlay-actions">
            <div class="action-button preview-btn" @click.stop="previewImage" title="预览图片">
              <el-icon><ZoomIn /></el-icon>
            </div>
            <div
              v-if="!disabled"
              class="action-button delete-btn"
              @click.stop="removeImage"
              title="删除图片"
            >
              <el-icon><Delete /></el-icon>
            </div>
          </div>
        </div>
      </div>
      
      <div v-else class="upload-placeholder">
        <el-icon class="upload-icon">
          <Plus />
        </el-icon>
        <div class="upload-text">{{ placeholder }}</div>
        <div v-if="tip || defaultTip" class="upload-tip">{{ tip || defaultTip }}</div>
      </div>
    </div>
   
    </el-upload>

    <!-- 图片预览对话框 -->
    <el-dialog v-model="previewVisible" title="图片预览" width="800px">
      <img :src="imageUrl" alt="预览图片" style="width: 100%; height: auto;" />
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, computed, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { Plus, ZoomIn, Delete, Loading, Picture } from '@element-plus/icons-vue'
import { useUserStore } from '@/modules/auth/store'

// Props
const props = defineProps({
  // 图片URL
  modelValue: {
    type: String,
    default: ''
  },
  // 文件分类 (avatar, image, product, banner等)
  category: {
    type: String,
    default: 'image'
  },
  // 是否禁用
  disabled: {
    type: Boolean,
    default: false
  },
  // 占位符文本
  placeholder: {
    type: String,
    default: '点击上传图片'
  },
  // 提示文本
  tip: {
    type: String,
    default: ''
  },
  // 图片alt属性
  alt: {
    type: String,
    default: '上传的图片'
  },
  // 允许的文件类型
  accept: {
    type: Array,
    default: () => ['image/jpeg', 'image/png', 'image/gif']
  },
  // 最大文件大小 (MB)
  maxSize: {
    type: Number,
    default: 2
  },
  // 图片尺寸限制
  dimensions: {
    type: Object,
    default: () => ({})
  },
  // 图片显示模式
  fit: {
    type: String,
    default: 'cover',
    validator: (value) => ['contain', 'cover', 'fill'].includes(value)
  }
})

// Emits
const emit = defineEmits(['update:modelValue', 'success', 'error'])

// 响应式数据
const uploadRef = ref()
const previewVisible = ref(false)
const imageLoading = ref(false)
const imageError = ref(false)
const userStore = useUserStore()

// 计算属性
const imageUrl = computed({
  get: () => props.modelValue,
  set: (value) => emit('update:modelValue', value)
})

const uploadUrl = computed(() => {
  return '/admin-api/v1/upload'
})

const uploadHeaders = computed(() => {
  const token = userStore.token
  return token ? { Authorization: `Bearer ${token}` } : {}
})

const uploadData = computed(() => {
  return { category: props.category }
})

const defaultTip = computed(() => {
  if (props.tip) return props.tip

  const sizeText = `大小不超过${props.maxSize}MB`
  const typeText = props.accept.map(type => {
    if (type.includes('jpeg')) return 'JPG'
    if (type.includes('png')) return 'PNG'
    if (type.includes('gif')) return 'GIF'
    return type.replace('image/', '').toUpperCase()
  }).join('/')

  return `支持${typeText}格式，${sizeText}`
})

// 上传前验证
const beforeUpload = (file) => {
  // 检查文件类型
  const isValidType = props.accept.some(type => {
    if (type.startsWith('image/')) {
      return file.type === type
    } else {
      return file.name.toLowerCase().endsWith(type.toLowerCase())
    }
  })
  
  if (!isValidType) {
    const typeText = props.accept.join(', ')
    ElMessage.error(`只能上传${typeText}格式的图片`)
    return false
  }

  // 检查文件大小
  const isValidSize = file.size / 1024 / 1024 < props.maxSize
  if (!isValidSize) {
    ElMessage.error(`图片大小不能超过${props.maxSize}MB`)
    return false
  }

  // 检查图片尺寸
  if (props.dimensions.width || props.dimensions.height) {
    return new Promise((resolve) => {
      const img = new Image()
      img.onload = () => {
        const { width, height } = props.dimensions
        
        if (width && img.width !== width) {
          ElMessage.error(`图片宽度必须为${width}px`)
          resolve(false)
          return
        }
        
        if (height && img.height !== height) {
          ElMessage.error(`图片高度必须为${height}px`)
          resolve(false)
          return
        }
        
        resolve(true)
      }
      img.onerror = () => {
        ElMessage.error('图片格式错误')
        resolve(false)
      }
      img.src = URL.createObjectURL(file)
    })
  }

  return true
}

// 上传成功
const handleSuccess = (response) => {
  console.log('上传响应:', response)
  if (response.code === 200) {
    // 从响应数据中获取文件URL
    const url = response.data.file_url
    console.log('设置图片URL:', url)
    
    if (url) {
      // 通过emit更新父组件的modelValue
      emit('update:modelValue', url)
      ElMessage.success('上传成功')
      emit('success', { ...response.data, url })
    } else {
      console.error('响应中没有找到图片URL字段:', response.data)
      ElMessage.error('上传成功但无法获取图片地址')
      emit('error', { message: '无法获取图片地址', response })
    }
  } else {
    ElMessage.error(response.message || '上传失败')
    emit('error', response)
  }
}

// 上传失败
const handleError = (error) => {
  console.error('上传失败:', error)
  ElMessage.error('上传失败，请重试')
  emit('error', error)
}

// 预览图片
const previewImage = () => {
  if (imageUrl.value) {
    previewVisible.value = true
  }
}

// 移除图片
const removeImage = () => {
  imageUrl.value = ''
  emit('update:modelValue', '')
}

// 图片加载处理
const handleImageLoadStart = () => {
  imageLoading.value = true
  imageError.value = false
}

const handleImageLoad = (event) => {
  imageLoading.value = false
  imageError.value = false

  // 调试信息
  const img = event.target
  console.log('图片加载完成:', {
    src: img.src,
    naturalWidth: img.naturalWidth,
    naturalHeight: img.naturalHeight,
    displayWidth: img.offsetWidth,
    displayHeight: img.offsetHeight,
    objectFit: img.style.objectFit,
    objectPosition: img.style.objectPosition
  })
}

const handleImageError = () => {
  imageLoading.value = false
  imageError.value = true
}

// 手动触发上传
const triggerUpload = () => {
  uploadRef.value?.$el.querySelector('input').click()
}

// 监听图片URL变化
watch(
  () => props.modelValue,
  (newUrl) => {
    console.log('图片URL变化:', newUrl)
    if (newUrl) {
      // 重置加载状态
      imageLoading.value = true
      imageError.value = false
      
      // 预加载图片以确保能正确显示
      const img = new Image()
      img.onload = () => {
        imageLoading.value = false
        console.log('图片预加载成功:', newUrl)
      }
      img.onerror = () => {
        imageLoading.value = false
        imageError.value = true
        console.error('图片预加载失败:', newUrl)
      }
      img.src = newUrl
    }
  },
  { immediate: true }
)

// 暴露方法
defineExpose({
  triggerUpload
})
</script>

<style scoped>
.image-upload {
  display: inline-block;
}

.image-uploader {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: border-color 0.3s;
  min-width: 120px;
  min-height: 120px;
  display: block;
}

.image-uploader:hover {
  border-color: #409eff;
}

.image-preview {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  border-radius: inherit;
  display: flex;
  align-items: center;
  justify-content: center;
}

.uploaded-image {
  width: 100%;
  height: 100%;
  display: block;
  background-color: #f5f7fa;
  transition: transform 0.3s ease;
  border-radius: inherit;
  /* object-fit 和 object-position 通过内联样式动态设置 */
}

/* hover 时轻微放大效果 */
.image-preview:hover .uploaded-image {
  transform: scale(1.02);
}

/* 图片加载状态 */
.image-loading,
.image-error {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background-color: #f5f7fa;
  color: #909399;
  border-radius: inherit;
  z-index: 5;
}

.loading-icon,
.error-icon {
  font-size: 24px;
  margin-bottom: 8px;
}

.loading-icon {
  animation: rotate 2s linear infinite;
}

.loading-text,
.error-text {
  font-size: 12px;
}

.error-text {
  color: #f56c6c;
}

@keyframes rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.image-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  transition: opacity 0.3s ease;
  border-radius: inherit;
  z-index: 10;
}

.image-preview:hover .image-overlay {
  opacity: 1;
}

.overlay-actions {
  display: flex;
  gap: 8px;
  align-items: center;
  justify-content: center;
}

.action-button {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background-color: rgba(255, 255, 255, 0.9);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: all 0.3s ease;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}

.action-button:hover {
  background-color: rgba(255, 255, 255, 1);
  transform: scale(1.1);
}

.action-button .el-icon {
  font-size: 16px;
}

.preview-btn .el-icon {
  color: #409eff;
}

.delete-btn .el-icon {
  color: #f56c6c;
}

.upload-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 20px;
  text-align: center;
  min-height: 120px;
}

.upload-icon {
  font-size: 28px;
  color: #8c939d;
  margin-bottom: 8px;
}

.upload-text {
  color: #606266;
  font-size: 14px;
  margin-bottom: 4px;
}

.upload-tip {
  color: #909399;
  font-size: 12px;
  line-height: 1.4;
}

/* 不同尺寸的样式 */
.image-upload.size-small .image-uploader {
  width: 80px;
  height: 80px;
}

.image-upload.size-medium .image-uploader {
  width: 120px;
  height: 120px;
}

.image-upload.size-large .image-uploader {
  width: 200px;
  height: 200px;
}

/* 头像样式 */
.image-upload.avatar .image-uploader {
  border-radius: 50%;
}

.image-upload.avatar .uploaded-image {
  border-radius: 50%;
}
</style>
